/*
 * @Author: wanglei 554623567@qq.com
 * @Date: 2024-10-24 10:06:00
 * @LastEditors: wanglei 554623567@qq.com
 * @LastEditTime: 2024-10-24 10:12:03
 * @FilePath: /forstep/lib/common/services/network/middleware/global_interceptor.dart
 * @Description: 错误中间件
 */

import 'dart:io';

import 'package:demo/common/extension/ex_string.dart';
import 'package:demo/common/net/interceptors/ex_options.dart';
import 'package:demo/common/utils/dialog_util.dart';
import 'package:demo/common/utils/string_util.dart';
import 'package:demo/common/utils/time_util.dart';
import 'package:demo/config/config.dart';
import 'package:demo/config/env_config.dart';
import 'package:dio/dio.dart';

import '../api_exception.dart';
import '../data/http_response_data.dart';

class GlobalInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
    // 公共头部信息
    if (options.addHeaders) {
      addHeaders(options);
    }
    // 签名
    if (options.addSign) {
      var sign = generateSignature(options);
      addParams(options, {"qianming": sign});
    }

    handler.next(options);
  }

  void addHeaders(RequestOptions options) {
    Map<String, dynamic> headers = {};
    var config = Config();

    headers['pingju'] = config.token;
    // 设备平台
    headers["kehuduan"] = Platform.operatingSystem;
    // 版本号
    headers["banben"] = config.getVersionName();
    headers["banbenhao"] = config.getVersionName().replaceAll(".", "");
    // 设备唯一标识
    headers["shebeihao"] = config.getDeviceId();
    // 国家
    headers["diqu"] = config.getCountryCode();
    //手机语言
    headers["yuyan"] = config.getLanguage();
    //所在时区
    headers["shiqu"] = config.getTimezone();
    //时区偏移
    headers["shiqu-xiaoshi"] = config.getTimezoneOffset();

    options.headers.addAll(headers);
  }

  /// 生成签名
  String generateSignature(RequestOptions options) {
    Map<String, String> params = {};

    // 时间戳和随机字符串
    final String time = TimeUtil.nowSeconds().toString();
    final String nonceStr = StringUtil.generateRandomString(10);

    // 公共签名参数
    final Map<String, String> signParams = {
      'app_key': platformConfig.appId,
      'shijianchuo': time,
      'suiji_str': nonceStr,
    };

    addParams(options, signParams);

    // 添加查询参数
    params.addAll(options.queryParameters.map((k, v) => MapEntry(k, v.toString())));

    // 添加 body 参数，排除文件
    if (options.data is Map) {
      // 普通 Map body
      params.addAll((options.data as Map).map((k, v) => MapEntry(k.toString(), v.toString())));
    } else if (options.data is FormData) {
      // FormData body，只签名 fields（非文件字段），忽略 files
      FormData formData = options.data as FormData;
      for (var entry in formData.fields) {
        params[entry.key] = entry.value;
      }
    }

    // 排序键
    List<String> sortedKeys = params.keys.toList()..sort();

    // 构建签名字符串
    String signString = sortedKeys.map((k) => "$k=${params[k]}").join("&");

    signString += "&key=${platformConfig.apiSignKey}";

    return signString.toMd5().toUpperCase();
  }

  /// 添加参数到请求中
  void addParams(RequestOptions options, Map<String, String> params) {
    // 添加到请求数据
    if (options.method == 'GET') {
      // GET 请求：添加到 queryParameters
      options.queryParameters = {...options.queryParameters, ...params};
    } else {
      // POST 请求
      if (options.data is Map) {
        // 普通 Map body：添加到 data
        options.data = {...options.data as Map, ...params};
      } else if (options.data is FormData) {
        // FormData body：添加到 fields
        final FormData formData = options.data as FormData;
        params.forEach((key, value) {
          formData.fields.add(MapEntry(key, value));
        });
        options.data = formData;
      }
    }
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    if (!response.requestOptions.asHttpResponseData) {
      handler.next(response);
      return;
    }

    final responseData = HttpResponseData.fromJson(response.data);
    response.data = responseData;

    if (responseData.zhuangtai == "y") {
      handler.next(response);
    } else {
      handler.reject(
        ApiException(
          requestOptions: response.requestOptions,
          response: response,
          responseModel: responseData,
          error: responseData.cuowuma,
          message: responseData.xinxi,
        ),
        true,
      );
    }
  }

  @override
  onError(DioException err, ErrorInterceptorHandler handler) {
    String errorMsg = "网络错误";
    switch (err.type) {
      case DioExceptionType.unknown:
        if (err is ApiException) {
          errorMsg = "";
          switch (err.error) {
            case 2001:
            case 2002:
            case 2003:
            case 2004:
              // todo token失效
              break;
            default:
              errorMsg = err.message ?? "";
              break;
          }
        }
        break;
      case DioExceptionType.cancel:
        // 请求取消
        errorMsg = "";
        break;
      default:
        break;
    }

    if (errorMsg.isNotEmpty && err.requestOptions.showErrorToast) {
      DialogUtil.showToast(errorMsg);
    }
    handler.next(err);
  }
}
